home *** CD-ROM | disk | FTP | other *** search
/ Aminet 21 / Aminet 21 (1997)(GTI - Schatztruhe)[!][Oct 1997].iso / Aminet / gfx / x11 / xmountains.lha / src / X_graphics.c < prev    next >
C/C++ Source or Header  |  1997-08-23  |  12KB  |  491 lines

  1. #include <stdio.h>
  2. #define USE_MACROS
  3. #include<X11/Xlib.h>
  4. #include<X11/Xutil.h>
  5. #include<X11/Xatom.h>
  6. #ifdef VROOT
  7. #include"vroot.h"
  8. #endif
  9. #include "paint.h"
  10.  
  11. #include "amigapragmas.h"
  12. #define NO_SLEEP
  13.  
  14. char X_graphics_Id[]="$Id: X_graphics.c,v 1.20 1995/01/20 15:13:06 spb Exp spb $";
  15.  
  16. char *display=NULL;       /* name of display to open, NULL for default */
  17. char *geom=NULL;          /* geometry of window, NULL for default */
  18.  
  19. Atom wm_protocols;
  20. Atom wm_delete_window;
  21.  
  22. #ifndef FALSE
  23. #define TRUE 1
  24. #define FALSE 0
  25. #endif
  26.  
  27.   int quit_xmount=FALSE;
  28.   Display *dpy;
  29.   int screen;
  30.   unsigned int graph_width;
  31.   unsigned int graph_height;
  32.   Window parent, win, root;
  33.   int use_root=FALSE;
  34.   int do_clear=FALSE;
  35.   int pixmap_installed=FALSE;
  36.  
  37.   /* plot history */
  38.   int plot_x, plot_y1, plot_y2;
  39.   unsigned long plot_col;
  40.   int plot_saved=FALSE;
  41.   
  42. #include "gray"
  43.  
  44.   Pixmap stip;
  45.   unsigned int depth=0;
  46.   GC gc;
  47.   Pixmap pix;
  48.   Colormap map, defaultmap;
  49.   XColor *table=NULL;
  50. void zap_events();
  51. void finish_graphics();
  52.   
  53. /*{{{void zap_events(int snooze)*/
  54. void zap_events(snooze)
  55. int snooze;
  56. {
  57.   XEvent event;
  58.   XExposeEvent *expose = (XExposeEvent *)&event;
  59.   int exw, exh, i;
  60.  
  61. #ifndef NO_SLEEP
  62.   i=0;
  63.   do{
  64. #endif
  65.   while( XPending(dpy) ){
  66.     XNextEvent(dpy, &event);
  67.     switch(event.type) {
  68.       case ClientMessage:
  69.         if (event.xclient.message_type == wm_protocols &&
  70.           event.xclient.data.l[0] == wm_delete_window)  {
  71.             quit_xmount=TRUE;
  72.           }
  73.             break;
  74.         case ButtonPress:
  75.             break;
  76.         case ButtonRelease:
  77.               quit_xmount=TRUE;
  78.             break;
  79.         case Expose:
  80.           if( (expose->x < graph_width) && (expose->y < graph_height))
  81.           {
  82.             if( (expose->x + expose->width) > graph_width)
  83.             {
  84.               exw=graph_width - expose->x;
  85.             }else{
  86.               exw = expose->width;
  87.             }
  88.             if( (expose->y + expose->height) > graph_height)
  89.             {
  90.               exh=graph_height - expose->y;
  91.             }else{
  92.               exh = expose->height;
  93.             }
  94.             XCopyArea(dpy,pix,win,gc,expose->x,expose->y,
  95.                           exw,exh,
  96.                           expose->x,expose->y);
  97.       }
  98.       break;
  99.         default:
  100.             fprintf(stderr,"xmountains: unrecognized event %d\n",event.type);
  101.             /* XCloseDisplay(dpy);
  102.              * exit(1);
  103.              */
  104.             break;
  105.     }
  106.   }
  107.   if( quit_xmount )
  108.   {
  109.     finish_graphics();
  110.     finish_artist();
  111.     exit(0);
  112.   }
  113. #ifndef NO_SLEEP
  114.     /* sleeping is very bad because it will prevent
  115.      * events being processed but I suppose it is better
  116.      * than being a CPU hog, as a compremise always check for
  117.      * events at least once a second, looping for longer sleep times.
  118.      * process the events before a sleep to make sure the screen is up to date.
  119.      * the events must always be processed at least once.
  120.      */
  121.     if( snooze )
  122.     {
  123.       sleep(1);
  124.     }
  125.     i++;
  126.   }while( i<snooze );
  127. #endif
  128. }
  129. /*}}}*/
  130.   
  131. /*{{{void finish_graphics()*/
  132. void finish_graphics()
  133. {
  134.   unsigned long attmask;
  135.   XSetWindowAttributes attributes;
  136.   int x,y;
  137.   unsigned int border;
  138.   int count;
  139.   
  140.   XFreePixmap(dpy,pix);
  141.   XFreeGC(dpy,gc);
  142.   XFreePixmap(dpy,stip);
  143.  
  144.   /* reset things if this was the root window. */
  145.   if( use_root )
  146.   {
  147.     if( pixmap_installed &&  do_clear )
  148.     {
  149.       /* restore default pixmap for the root window */
  150.       XSetWindowBackgroundPixmap(dpy,win,ParentRelative);
  151.       XClearWindow(dpy,win);
  152.     }else{
  153.       XGetGeometry(dpy,win,&root,&x,&y,&graph_width,&graph_height,&border,&depth);
  154.       XClearArea(dpy,win,0,0,graph_width,graph_height,FALSE);
  155.     }
  156.     if( map != defaultmap )
  157.     {
  158.       attmask = 0;
  159.       attmask |= CWColormap;
  160.       attributes.colormap = defaultmap;
  161.       XChangeWindowAttributes(dpy,win,attmask,&attributes);
  162.     }
  163.   }
  164.   if( map != defaultmap )
  165.   {
  166.     XFreeColormap(dpy, map );
  167.   }
  168.   if( count = XPending(dpy) )
  169.   {
  170.     fprintf(stderr,"WARNING: %d events still pending\n",count);
  171.   }
  172.   XCloseDisplay(dpy);
  173. }
  174. /*}}}*/
  175.  
  176. /*{{{void blank_region(lx,ly,ux,uy)*/
  177. void blank_region(lx,ly,ux,uy)
  178. int lx,ly,ux,uy;
  179. {
  180.   if( depth < 4 )
  181.   {
  182.     /* use a textured gray sky on monochrome displays
  183.      * we may need this on any low-depth display
  184.      */
  185.     XSetForeground(dpy,gc,WhitePixel(dpy,screen));
  186.     XSetFillStyle(dpy,gc,FillOpaqueStippled);
  187.     XFillRectangle(dpy,pix,gc,lx,ly,ux,uy);
  188.     XSetFillStyle(dpy,gc,FillSolid);
  189.   }else{
  190.     XSetForeground(dpy,gc,table[SKY].pixel);
  191.     XFillRectangle(dpy,pix,gc,lx,ly,ux,uy);
  192.   }
  193. }
  194. /*}}}*/
  195.  
  196. /*{{{void init_graphics( ... )*/
  197. void init_graphics( want_use_root, use_background, want_clear, s_graph_width,s_graph_height,ncol,red,green,blue )
  198. int want_use_root;    /* display on the root window */
  199. int  use_background;  /* install the pixmap as the background-pixmap */
  200. int want_clear;
  201. int *s_graph_width;
  202. int *s_graph_height;
  203. int ncol;
  204. Gun *red;
  205. Gun *green;
  206. Gun *blue;
  207. {
  208. /*{{{defs*/
  209.   Visual *vis;
  210.   int mask;
  211.   int count;
  212.   int x=0;
  213.   int y=0;
  214.   int gbits=0;
  215.   unsigned long attmask;
  216.   XSetWindowAttributes attributes;
  217.   char * winname="Xmountains";
  218.   XTextProperty textprop;
  219.  
  220.   unsigned int border;
  221.   unsigned long gcvmask;
  222.   XGCValues gcv;
  223.   
  224.   int i;
  225.   int newmap=FALSE;
  226.  
  227. /*}}}*/
  228.  
  229.   do_clear = want_clear;
  230.   use_root = want_use_root;
  231.   pixmap_installed = use_background;
  232.   graph_width = *s_graph_width;
  233.   graph_height = *s_graph_height;
  234. /*{{{open display*/
  235.  
  236.   dpy = XOpenDisplay(display);
  237.   
  238.   if( ! dpy )
  239.   {
  240.     fprintf(stderr,"failed to open display\n");
  241.     exit(1);
  242.   }
  243.   screen = DefaultScreen(dpy);
  244.   parent = RootWindow(dpy, screen);
  245. /*}}}*/
  246. /*{{{find appropriate vis*/
  247.   map=defaultmap=DefaultColormap(dpy,screen);
  248.   vis = DefaultVisual(dpy,screen);
  249.   depth = DefaultDepth(dpy,screen);
  250. /*}}}*/
  251. /*{{{set colormap*/
  252.   table=(XColor *)malloc(ncol * sizeof(XColor));
  253.   if( NULL == table )
  254.   {
  255.     fprintf(stderr,"malloc failed for colour table\n");
  256.     exit(1);
  257.   }
  258.   for(i=0; i<ncol ; i++)
  259.   {
  260.     table[i].red   = red[i];
  261.     table[i].green = green[i];
  262.     table[i].blue  = blue[i];
  263.     while( ! XAllocColor(dpy,map,table+i) )
  264.     {
  265.       if( newmap ){
  266.         fprintf(stderr,"failed to allocate colour %d\n",i);
  267.         XCloseDisplay(dpy);
  268.         exit(1);
  269.       }else{
  270.         map = XCopyColormapAndFree(dpy,map);
  271.         newmap=TRUE;
  272.       }
  273.     }
  274.   }
  275. /*}}}*/
  276. /*{{{create window*/
  277.   attmask = 0;
  278.   if( use_root )
  279.   {
  280.     win = parent;
  281.     if( ! use_background )
  282.     {
  283.       attmask |= CWEventMask;
  284.       attributes.event_mask = ExposureMask; /* catch expose events */
  285.     }
  286.     attmask |= CWColormap;
  287.     attributes.colormap = map;
  288.     XChangeWindowAttributes(dpy,win,attmask,&attributes);
  289.   }else{
  290.     if( geom )
  291.     {
  292.       gbits =XParseGeometry(geom,&x,&y,&graph_width,&graph_height);
  293.       if((gbits & XValue) && (gbits & XNegative))
  294.       {
  295.         x += DisplayWidth(dpy,screen) - graph_width;
  296.       }
  297.       if((gbits & YValue) && (gbits & YNegative))
  298.       {
  299.         y += DisplayHeight(dpy,screen) - graph_height;
  300.       }
  301.     }
  302.     attmask |= CWEventMask;
  303.     if( ! use_background )
  304.     {
  305.       attributes.event_mask = ButtonPressMask|ButtonReleaseMask|ExposureMask;
  306.     }else{
  307.       attributes.event_mask = ButtonPressMask|ButtonReleaseMask;
  308.     }
  309.     attmask |= CWBackPixel;
  310.     attributes.background_pixel = BlackPixel(dpy,screen);
  311.     attmask |= CWBackingStore;
  312.     attributes.backing_store = NotUseful;
  313.     attmask |= CWColormap;
  314.     attributes.colormap = map;
  315.     win = XCreateWindow(dpy,parent,x,y,graph_width,graph_height,0,
  316.       depth,InputOutput,vis,attmask,&attributes);
  317.   
  318.     /* Setup for ICCCM delete window. */
  319.     wm_protocols = XInternAtom(dpy, "WM_PROTOCOLS", False);
  320.     wm_delete_window = XInternAtom(dpy, "WM_DELETE_WINDOW", False);
  321.     (void) XSetWMProtocols (dpy, win, &wm_delete_window, 1);
  322.     textprop.value = (unsigned char *) winname;
  323.     textprop.encoding = XA_STRING;
  324.     textprop.format = 8;
  325.     textprop.nitems = strlen(winname);
  326.     XSetWMName(dpy,win,&textprop);
  327.   }
  328. /*}}}*/
  329. /*{{{create pixmap*/
  330.   XGetGeometry(dpy,win,&root,&x,&y,&graph_width,&graph_height,&border,&depth);
  331.   stip = XCreateBitmapFromData(dpy,win,gray_bits,gray_width,gray_height);
  332.  
  333.   gcvmask = 0;
  334.   gcvmask |= GCForeground;
  335.   gcv.foreground = WhitePixel(dpy,screen);
  336.   gcvmask |= GCBackground;
  337.   gcv.background = BlackPixel(dpy,screen);
  338.   gcvmask |= GCGraphicsExposures;
  339.   gcv.graphics_exposures = FALSE;
  340.   gcvmask |= GCStipple;
  341.   gcv.stipple = stip;
  342.   gcvmask |= GCFillStyle;
  343.   gcv.fill_style = FillSolid;
  344.   gcv.graphics_exposures = FALSE;
  345.   
  346.   gc = XCreateGC(dpy,win,gcvmask,&gcv);
  347.  
  348.   /* if we are going to install this as a root pixmap, throw away
  349.    * the old one FIRST. this reduces fragmentation
  350.    */
  351.   if( use_background && use_root )
  352.   {
  353.     XSetWindowBackgroundPixmap(dpy,win,None);
  354.   }
  355.   if( use_root )
  356.   {
  357.     /* in case of virtual window manager set to size of display */
  358.     graph_width = DisplayWidth(dpy,screen);
  359.     graph_height = DisplayHeight(dpy,screen);
  360.   }
  361.   pix = XCreatePixmap(dpy,win,graph_width,graph_height,depth);
  362.  
  363. /*}}}*/
  364.   blank_region(0,0,graph_width,graph_height); 
  365.  
  366.   if( use_background )
  367.   {
  368.     XSetWindowBackgroundPixmap(dpy,win,pix);
  369.   }
  370.   if( ! use_root )
  371.   {
  372.     XMapWindow(dpy, win );
  373.   }
  374.   XClearWindow(dpy,win);
  375.   zap_events(0);
  376.   
  377.   *s_graph_width = graph_width;
  378.   *s_graph_height = graph_height;
  379. }
  380. /*}}}*/
  381.  
  382. /*{{{void scroll_screen( int dist )*/
  383. void scroll_screen( dist )
  384. int dist;
  385. {
  386.   int reverse=FALSE;
  387.  
  388.   if( dist < 0 )
  389.   {
  390.     dist = -dist;
  391.     reverse=TRUE;
  392.   }
  393.   /* scroll the pixmap */
  394.   if( dist > graph_width )
  395.   {
  396.     dist = graph_width;
  397.   }
  398.   if( reverse )
  399.   {
  400.     /* copy the data */
  401.     XCopyArea(dpy,pix,pix,gc,0,0,graph_width-dist,graph_height,dist,0);
  402.     /* blank new region */
  403.     blank_region(0,0,dist,graph_height);
  404.   }else{
  405.     /* copy the data */
  406.     XCopyArea(dpy,pix,pix,gc,dist,0,graph_width-dist,graph_height,0,0);
  407.     /* blank new region */
  408.     blank_region(graph_width-dist,0,dist,graph_height);
  409.   }
  410.   /* update the window to match */
  411.   if( pixmap_installed )
  412.   {
  413.     XClearWindow(dpy,win);
  414.   }else{
  415.     XCopyArea(dpy,pix,win,gc,0,0,graph_width,graph_height,0,0);
  416.   }
  417.  
  418. }
  419. /*}}}*/
  420.  
  421. /*{{{void plot_pixel( int x, int y, Gun value )*/
  422. void plot_pixel( x, y, value )
  423. int x;
  424. int y;
  425. Gun value;
  426. {
  427.   int do_draw, draw_x, draw_y1, draw_y2;
  428.   unsigned long draw_colour;
  429.   
  430.   /* if x is negative this means flush the stored request */
  431.   if(! plot_saved) /* no stored values */
  432.   {
  433.     plot_x = x;
  434.     plot_y1=plot_y2 = y;
  435.     plot_col=table[value].pixel;
  436.     do_draw=FALSE;
  437.     plot_saved = (x >=0);
  438.   }else{
  439.     if( x < 0 )  /* requesting a flush */
  440.     {
  441.       draw_x=plot_x;
  442.       draw_y1=plot_y1;
  443.       draw_y2=plot_y2;
  444.       draw_colour = plot_col;
  445.       plot_saved=FALSE;
  446.       do_draw=TRUE;
  447.     }else{      /* plot request with saved value */
  448.       if( (x==plot_x) && (plot_col == table[value].pixel)) /* add to line */
  449.       {
  450.         if(y<plot_y1) plot_y1=y;
  451.         if(y>plot_y2) plot_y2=y;
  452.         do_draw=FALSE;
  453.       }else{
  454.         draw_x=plot_x;
  455.         draw_y1=plot_y1;
  456.         draw_y2=plot_y2;
  457.         draw_colour=plot_col;
  458.         do_draw=TRUE;
  459.         plot_x=x;
  460.         plot_y1=plot_y2=y;
  461.         plot_col=table[value].pixel;
  462.       }
  463.     }
  464.   }
  465.   if( do_draw )
  466.   {
  467.     XSetForeground(dpy,gc,draw_colour);
  468.     if( draw_y1 == draw_y2 )
  469.     {
  470.       XDrawPoint(dpy,pix,gc,draw_x,draw_y1);
  471.     }else{
  472.       XDrawLine(dpy,pix,gc,draw_x,draw_y1,draw_x,draw_y2);
  473.     }
  474.   }
  475. }
  476. /*}}}*/
  477.  
  478. /*{{{void flush_region(int x, int y, int w, int h)*/
  479. void flush_region( x, y, w, h)
  480. int x;
  481. int y;
  482. int w;
  483. int h;
  484. {
  485.   /* flush outstanding plots */
  486.   plot_pixel(-1,0,0);
  487.   XCopyArea(dpy,pix,win,gc,x,y,w,h,x,y);
  488. }
  489. /*}}}*/
  490.  
  491.